use crate::{ReservationManager, Rsvp, config::Config};
use abi::reservation::{
    ListenRequest, ListenResponse, QueryRequest, Reservation, ReservationId, UpdateRequest,
    reservation_service_server::ReservationService,
};
use futures::Stream;
use std::pin::Pin;
use tonic::{Request, Response, Status, async_trait};

type ReservationStream = Pin<Box<dyn Stream<Item = Result<Reservation, Status>> + Send>>;
type OperateStream = Pin<Box<dyn Stream<Item = Result<ListenResponse, Status>> + Send>>;

pub struct RsvpService(ReservationManager);

impl RsvpService {
    pub async fn from_config(config: Config) -> Result<Self, anyhow::Error> {
        Ok(Self(ReservationManager::from_config(&config.db).await?))
    }
}

#[async_trait]
impl ReservationService for RsvpService {
    async fn reserve(
        &self,
        request: Request<Reservation>,
    ) -> Result<Response<Reservation>, Status> {
        let reservation = request.into_inner();
        let reservation = self.0.reserve(reservation).await?;

        Ok(Response::new(reservation))
    }

    async fn confirm(
        &self,
        _request: Request<ReservationId>,
    ) -> Result<Response<Reservation>, Status> {
        todo!()
    }

    async fn update(
        &self,
        _request: Request<UpdateRequest>,
    ) -> Result<Response<Reservation>, Status> {
        todo!()
    }

    async fn cancel(
        &self,
        _request: Request<ReservationId>,
    ) -> Result<Response<Reservation>, Status> {
        todo!()
    }

    type queryStream = ReservationStream;
    async fn query(
        &self,
        _request: Request<QueryRequest>,
    ) -> Result<Response<Self::queryStream>, Status> {
        todo!()
    }

    type listenStream = OperateStream;
    async fn listen(
        &self,
        _request: Request<ListenRequest>,
    ) -> Result<Response<Self::listenStream>, Status> {
        todo!()
    }
}
